#include "aurasim.h"

#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include "views/mainwindow.h"
#include "systems/connectorsystem.h"
#include "systems/circuitsimsystem.h"
#include <QtConcurrent>

Aurasim::AurasimApp::AurasimApp(QObject *parent):
    QObject (parent),
    systemManager(QSharedPointer<SystemManager>(new SystemManager)),
    entityManger(QSharedPointer<EntityManager>(new EntityManager)),
    mouseDraggingState(false),
    simState(Aurasim::Stop),
    board(nullptr)
{
    mTimerCounter.start();
    startTimer(1, Qt::PreciseTimer);
}

Aurasim::AurasimApp *Aurasim::AurasimApp::instance()
{
    static AurasimApp instance;
    return &instance;
}

void Aurasim::AurasimApp::updateSelectedEntity(QList<QGraphicsItem *> items)
{
    selectedEntities.clear();
    foreach (QGraphicsItem* item, items) {
        Entity* entity = static_cast<Entity*>(item);
        if(entity)
            selectedEntities << entity;
    }
}

void Aurasim::AurasimApp::timerEvent(QTimerEvent *e)
{
    Aurasim::systemManager()->tick(mTimerCounter.elapsed());
    Aurasim::entityManager()->tick(mTimerCounter.elapsed());
    mTimerCounter.restart();
    QObject::timerEvent(e);
}

void Aurasim::init()
{

    // instantiate app
    AurasimApp::instance();

    // show app window
    QSize desktopSize = qApp->screens().first()->availableGeometry().size();
    MainWindow* appWindow = new MainWindow;
    appWindow->resize(desktopSize * 0.5);
    appWindow->move((desktopSize.width() - appWindow->width()) / 2, (desktopSize.height() - appWindow->height()) / 2);
    appWindow->show();

    ConnectorSystem* connSys = new ConnectorSystem;
    CircuitSimSystem* cirSys = new CircuitSimSystem;

    Aurasim::systemManager()->addSystem(connSys);
    Aurasim::systemManager()->addSystem(cirSys);

    // test
    Entity* unoBoard = Aurasim::newEntity("UnoBoard");
    Aurasim::app()->board = QSharedPointer<Entity>(unoBoard);
    Aurasim::entityManager()->addEntity(unoBoard);
}

Aurasim::AurasimApp *Aurasim::app()
{
    return AurasimApp::instance();
}

const QSharedPointer<SystemManager> &Aurasim::systemManager()
{
    return AurasimApp::instance()->systemManager;
}

const QSharedPointer<EntityManager> &Aurasim::entityManager()
{
    return AurasimApp::instance()->entityManger;
}

const EntityList &Aurasim::selectedEntities()
{
    return AurasimApp::instance()->selectedEntities;
}

bool Aurasim::mouseDraggingState()
{
    return AurasimApp::instance()->mouseDraggingState;
}

void Aurasim::setMouseDraggingState(const bool &state)
{
    AurasimApp::instance()->mouseDraggingState = state;
}

void Aurasim::startSim()
{
    assert(Aurasim::app()->board);
    Aurasim::app()->board->start();
    Aurasim::app()->simState = Aurasim::Start;
    emit  Aurasim::app()->simStateChanged(Aurasim::app()->simState);
}

void Aurasim::stopSim()
{
    assert(Aurasim::app()->board);
    Aurasim::app()->board->stop();
    Aurasim::app()->simState = Aurasim::Stop;
    emit  Aurasim::app()->simStateChanged(Aurasim::app()->simState);
}
